﻿using System;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using XISoft.AppCreator.CommonUI;
using XISoft.AppCreator.Util.Common;
using XISoft.AppCreator.UI.UMLDesigner;



namespace XISoft.AppCreator.CommonUI.UML
{
    public partial class ClassObject : UserControl
    {
        private const String ProperyHeader = "ProperyHeader";
        private const String FiledHeader = "FiledHeader";
        private const String MethodHeader = "MethodHeader";
        private const String EventHeader = "EventHeader";

        private ClassObject()
        {
            InitializeComponent();
            this.BackColor = Color.Transparent;
            this.DoubleBuffered = true;
        }

        public readonly DataTable entity;
        private readonly DataRow eDataRow;
        public ClassObject(DataRow edr, DataTable dt)
            :this()
        {
            entity = dt;
            eDataRow = edr;
            init();

        }
        public void init()
        {
            Boolean find = false;
            this.SuspendLayout();
            do
            {
                find = false;
                foreach (Control c in Controls)
                    if (c is ItemPanel)
                    {
                        c.Dispose();
                        Controls.Remove(c);
                        find = true;
                    }
            } while (find);

            if (entity.Rows.Count == 0)
            {
                DataRow dr = entity.NewRow();
                dr[ModelDataDictionary.EntityTable.Name] = "Id";
                dr[ModelDataDictionary.EntityTable.Code] = "Id";
                dr[ModelDataDictionary.EntityTable.DataType] = "string";
                dr[ModelDataDictionary.EntityTable.Length] = "36";
                dr[ModelDataDictionary.EntityTable.isPrimaryKey] = true;
                dr[ModelDataDictionary.EntityTable.isNullable] = false;
                entity.Rows.Add(dr);
            }

            ItemPanel _itempanelProperty = new ItemPanel(ClassSon.Attribute, this);
            ItemPanel _itempanelMethod = new ItemPanel(ClassSon.Method, this);


            _itempanelProperty.SuspendLayout();
            _itempanelMethod.SuspendLayout();

            for (int i = 0; i < entity.Rows.Count;i++ )
            {
                DataRow dr = entity.Rows[i];
                if (dr[ModelDataDictionary.EntityTable.Type].ToString() == "Attribute")
                    _itempanelProperty.AddItem(false, dr[ModelDataDictionary.EntityTable.Name].ToString() + " : " + dr[ModelDataDictionary.EntityTable.DataType].ToString(), ClassSon.Attribute,i);
                else
                    _itempanelMethod.AddItem(false, dr[ModelDataDictionary.EntityTable.Name].ToString() + " : " + dr[ModelDataDictionary.EntityTable.DataType].ToString(), ClassSon.Method,i);
            }


            this.Controls.Add(_itempanelProperty);
            _itempanelProperty.Name = ProperyHeader;
            _itempanelProperty.Top = 51;

            _itempanelProperty.ResumeLayout(false);
            _itempanelMethod.ResumeLayout(false);
            if (_itempanelMethod.Controls.Count > 1)
            {
                this.Controls.Add(_itempanelMethod);
                _itempanelMethod.Name = MethodHeader;
                _itempanelMethod.Top = _itempanelProperty.Bottom;
            }
            else _itempanelMethod.Dispose();


            this.Name = entity.TableName;

            this.ResumeLayout(false);
        }


        private bool _isSelected = false;
        private bool _expanded = false;

        #region classObject event
        private void ClassObject_Load(object sender, EventArgs e)
        {

            this.SendToBack();
            this.BackColor = Color.Transparent;
            
        }
       

        private void ClassObject_Paint(object sender, PaintEventArgs e)
        {
            DrawPieRectangle(e.Graphics, this.ClientRectangle);
            DrawTitle(e.Graphics);
        }

        private void ClassObject_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.X > 5 && e.X < this.Name.Length * 8 && e.Y > 1 && e.Y < 12)
            {
                this.Cursor = Cursors.IBeam;
            }
            else
            {
                this.Cursor = Cursors.Default;
            }
        }

        private void ClassObject_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.X > 5 && e.X < this.Name.Length * 8 && e.Y > 1 && e.Y < 12)
            {
                if (!_isSelected)
                {
                    _isSelected = true;
                }
                else
                {
                    TextBox textBox = new TextBox();
                    textBox.Location = new Point(5, 2);
                    textBox.Text = this.Name;
                    textBox.KeyDown += new KeyEventHandler(EditorName_KeyDown);
                    textBox.Leave += new EventHandler(textBox_Leave);
                    this.Controls.Add(textBox);
                }
            }
            else
            {
                foreach (Control ctrl in this.Controls)
                {
                    if (ctrl.GetType().ToString() == "System.Windows.Forms.TextBox")
                    {
                        this.Name = ctrl.Text;
                        this.Controls.Remove(ctrl);
                    }
                    _isSelected = false; this.Refresh();
                }
            }
        }

        private void ClassObject_Resize(object sender, EventArgs e)
        {
            foreach (Control c in Controls)
            {
                if (c is ItemPanel)
                    c.Width = Width - 2;
            }
            pictureBox1.Left = this.Width - pictureBox1.Width - 5;
        }
        #endregion

        #region 绘制元件标题
        private void DrawTitle(Graphics g)
        {
            g.DrawString(this.Name, new Font("黑体", 9, FontStyle.Bold), new SolidBrush(Color.Black), new PointF(8, 2));
            if (_isSelected)
            {
                Pen _selectPen = new Pen(Color.Black);
                _selectPen.DashStyle = DashStyle.Dot;
                g.DrawRectangle(_selectPen, new Rectangle(5,2,8*this.Name.Length,12));
            }
        }
        #endregion

        #region 绘制ClassObject骨架
        private void DrawPieRectangle(Graphics g, Rectangle rect)
        {          
            SortHeader();
            GraphicsPath path = new GraphicsPath();
            path.AddArc(new Rectangle(rect.Width - 17, 0, 16, 16), 270, 90);
            path.AddLine(new Point(rect.Width - 1, 8), new Point(rect.Width - 1, rect.Height - 8));
            path.AddArc(new Rectangle(rect.Width - 17, rect.Height - 17, 16, 16), 0, 90);
            path.AddLine(new Point(9, rect.Height - 1), new Point(rect.Width - 8, rect.Height - 1));
            path.AddArc(new Rectangle(0, rect.Height - 17, 16, 16), 90, 90);
            path.AddLine(new Point(0, 8), new Point(0, rect.Height - 8));
            path.AddArc(new Rectangle(0, 0, 16, 16), 180, 90);
            path.AddLine(new Point(8, 0), new Point(rect.Width - 8, 0));
            g.DrawPath(new Pen(new SolidBrush(Color.CornflowerBlue)), path);
            path.ClearMarkers();
            path = new GraphicsPath();
            if (!_expanded)
            {
                path.AddArc(new Rectangle(rect.Width - 17, 1, 16, 16), 270, 90);
                path.AddLine(new Point(rect.Width - 1, 8), new Point(rect.Width - 1, rect.Height - 8));
                path.AddArc(new Rectangle(rect.Width - 17, rect.Height - 17, 16, 16), 0, 90);
                path.AddLine(new Point(8, rect.Height - 1), new Point(rect.Width - 8, rect.Height - 1));
                path.AddArc(new Rectangle(0, rect.Height - 17, 16, 16), 90, 90);
                path.AddLine(new Point(1, 8), new Point(1, rect.Height - 8));
                path.AddArc(new Rectangle(0, 0, 16, 16), 180, 90);
                path.AddLine(new Point(8, 1), new Point(rect.Width - 8, 1));
            }
            else
            {
                path.AddLine(new Point(1, 50), new Point(1, 8));
                path.AddArc(new Rectangle(0, 0, 16, 16), 180, 90);
                path.AddLine(new Point(8, 1), new Point(rect.Width - 8, 1));
                path.AddArc(new Rectangle(rect.Width - 17, 1, 16, 16), 270, 90);
                path.AddLine(new Point(rect.Width - 1, 8), new Point(rect.Width - 1, 50));
                path.AddLine(new Point(1, 50), new Point(rect.Width - 1, 50));
                g.DrawLine(new Pen(Color.CornflowerBlue), new Point(1, 50), new Point(this.Width - 2, 50));
            }
            g.FillPath(new LinearGradientBrush(new Rectangle(0, 0, this.Width, 50), Color.FromArgb(100, 100, 190), Color.FromArgb(255, 255, 255), 8, true), path);
            g.DrawString("Class", new Font("宋体", 8), new SolidBrush(Color.BlanchedAlmond), new PointF(8, 25));
        }
        #endregion

        #region 绘制_expanded元件
        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            Rectangle rect = this.pictureBox1.ClientRectangle;
            GraphicsPath path = new GraphicsPath();
            path.AddArc(new Rectangle(rect.Width - 9, 0, 8, 8), 270, 90);
            path.AddLine(new Point(rect.Width - 1, 5), new Point(rect.Width - 1, rect.Height - 5));
            path.AddArc(new Rectangle(rect.Width - 9, rect.Height - 9, 8, 8), 0, 90);
            path.AddLine(new Point(5, rect.Height - 1), new Point(rect.Width - 5, rect.Height - 1));
            path.AddArc(new Rectangle(0, rect.Height - 9, 8, 8), 90, 90);
            path.AddLine(new Point(0, 5), new Point(0, rect.Height - 5));
            path.AddArc(new Rectangle(0, 0, 8, 8), 180, 90);
            path.AddLine(new Point(5, 0), new Point(rect.Width - 5, 0));
            e.Graphics.DrawPath(new Pen(new SolidBrush(Color.LightBlue), (float)0.5), path);
            if (!_expanded)
            {
                e.Graphics.DrawLine(new Pen(new SolidBrush(Color.DarkBlue), (float)0.5), new Point(3, 3), new Point(7, 7));
                e.Graphics.DrawLine(new Pen(new SolidBrush(Color.DarkBlue), (float)0.5), new Point(7, 7), new Point(11, 3));

                e.Graphics.DrawLine(new Pen(new SolidBrush(Color.DarkBlue), (float)0.5), new Point(3, 7), new Point(7, 11));
                e.Graphics.DrawLine(new Pen(new SolidBrush(Color.DarkBlue), (float)0.5), new Point(7, 11), new Point(11, 7));
            }
            else
            {
                /*e.Graphics.DrawLine(new Pen(new SolidBrush(Color.Red), (float)0.5), new Point(pictureBox1.Width - 3, pictureBox1.Height - 3), new Point(pictureBox1.Width - 7, pictureBox1.Height - 7));
                e.Graphics.DrawLine(new Pen(new SolidBrush(Color.Red), (float)0.5), new Point(pictureBox1.Width - 7, pictureBox1.Height - 7), new Point(pictureBox1.Width - 11, pictureBox1.Height - 3));

                e.Graphics.DrawLine(new Pen(new SolidBrush(Color.Red), (float)0.5), new Point(pictureBox1.Width - 3, pictureBox1.Height - 7), new Point(pictureBox1.Width - 7, pictureBox1.Height - 11));
                e.Graphics.DrawLine(new Pen(new SolidBrush(Color.Red), (float)0.5), new Point(pictureBox1.Width - 7, pictureBox1.Height - 11), new Point(pictureBox1.Width - 11, pictureBox1.Height - 7));
                */

                e.Graphics.DrawLine(new Pen(new SolidBrush(Color.DarkBlue), (float)0.5), new Point(3,7), new Point(7, 3));
                e.Graphics.DrawLine(new Pen(new SolidBrush(Color.DarkBlue), (float)0.5), new Point(7, 3), new Point(11, 7));

                e.Graphics.DrawLine(new Pen(new SolidBrush(Color.DarkBlue), (float)0.5), new Point(3, 11), new Point(7, 7));
                e.Graphics.DrawLine(new Pen(new SolidBrush(Color.DarkBlue), (float)0.5), new Point(7, 7), new Point(11, 11));
            }
        }
        #endregion

        private void pictureBox1_Click(object sender, EventArgs e)
        {
            _expanded = !_expanded;
            this.pictureBox1.Refresh();
            this.Refresh();
        }

        private void textBox_Leave(object sender, EventArgs e)
        {
            eDataRow[ModelDataDictionary.MainClass.Name] = ((TextBox)sender).Text;
            if (CheckSameName())
            {
                this.entity.TableName = ((TextBox)sender).Text;
                this.Name = ((TextBox)sender).Text;
                this.Controls.Remove((TextBox)sender);
                this.Refresh();
            }
            else
            {
                eDataRow[ModelDataDictionary.MainClass.Name] = this.Name;
                MessageBox.Show("有同名", "有同名", MessageBoxButtons.OKCancel, MessageBoxIcon.Error);
            }

            this.Controls.Remove((TextBox)sender);
        }

        private void EditorName_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                eDataRow[ModelDataDictionary.MainClass.Name] = ((TextBox)sender).Text;
                if (CheckSameName())
                {
                    this.entity.TableName = ((TextBox)sender).Text;
                    this.Name = ((TextBox)sender).Text;
                    this.Controls.Remove((TextBox)sender);
                    this.Refresh();
                }
                else
                {
                    eDataRow[ModelDataDictionary.MainClass.Name] = this.Name;
                    MessageBox.Show("有同名");
                }
            }
            if (e.KeyCode == Keys.Escape)
            {
                this.Controls.Remove((TextBox)sender);
                this.Refresh();
            }
        }

        /// <summary>
        /// 对Header对像最佳匹配
        /// </summary>
        public void SortHeader()
        {
            if (_expanded)
            {                
                int _Top = 50;
                foreach (Control ctrl in Controls)
                {
                    if (ctrl.GetType()== typeof(ItemPanel))
                    {
                        ctrl.Location = new Point(1, _Top);
                        _Top = ctrl.Bottom;
                    }                    
                }
                Height = _Top + 20;
            }
            else
            {
                Height = 50;
            }
        }

        //添加项控件
        private void DoAdd(string Type, ClassSon _classson)
        {
            _expanded = true;
            bool hasPropertyHeader = false;

            foreach (Control ctrl in this.Controls)
            {
                if (ctrl.Name == Type)
                {
                    ((ItemPanel)ctrl).AddItem(false, String.Empty, _classson);
                    hasPropertyHeader = true;
                }

            }
            if (!hasPropertyHeader)
            {
                ItemPanel _itempannel = new ItemPanel(_classson, this);

                _itempannel.AddItem(false, String.Empty, _classson);
                _itempannel.Name = Type;
                this.Controls.Add(_itempannel);
            }

            this.Refresh();
        }

        /// <summary>
        /// 添加特殊的元素
        /// </summary>
        /// <param name="_classson">类型</param>
        /// <param name="caption">显示名称</param>
        private void AddSepcialItem(ClassSon _classson, string caption)
        {
            _expanded = true;
            bool hasPropertyHeader = false;
            foreach (Control ctrl in this.Controls)
            {
                if (_classson == ClassSon.Method)
                {
                    if (ctrl.Name == MethodHeader)
                    {
                        ((ItemPanel)ctrl).AddItem(true, caption, _classson);
                        hasPropertyHeader = true;
                    }
                }
                if (_classson == ClassSon.Filed)
                {
                    if (ctrl.Name == FiledHeader)
                    {
                        ((ItemPanel)ctrl).AddItem(true, caption, ClassSon.Filed);
                        hasPropertyHeader = true;
                    }
                }
            }
            if (!hasPropertyHeader)
            {
                ItemPanel _itempannel = new ItemPanel(_classson, this);
                _itempannel.AddItem(true, caption, _classson);

                if (_classson == ClassSon.Method)
                    _itempannel.Name = MethodHeader;
                else
                    _itempannel.Name = FiledHeader;
                this.Controls.Add(_itempannel);
            }
            this.Refresh();
        }

        #region popMenu event
        private void popAddProperty_Click(object sender, EventArgs e)
        {
            DoAdd(ProperyHeader, ClassSon.Attribute);
        }


        private void popAddField_Click(object sender, EventArgs e)
        {
            DoAdd(FiledHeader, ClassSon.Filed);
        }
        private void popAddMethod_Click(object sender, EventArgs e)
        {
            DoAdd(MethodHeader, ClassSon.Method);
        }

        private void popAddEvent_Click(object sender, EventArgs e)
        {
            DoAdd(EventHeader, ClassSon.Event);
        }

        private void popAbout_Click(object sender, EventArgs e)
        {
            AboutForm about = new AboutForm();
            about.ShowDialog();
        }

        /// <summary>
        ///构造函数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void popAddCon_Click(object sender, EventArgs e)
        {
            AddSepcialItem(ClassSon.Method, this.Name);
        }

        /// <summary>
        /// 析构函数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void popAddDeCon_Click(object sender, EventArgs e)
        {
            AddSepcialItem(ClassSon.Method, "~" + this.Name);
        }

        private void popAddConstant_Click(object sender, EventArgs e)
        {
            AddSepcialItem(ClassSon.Filed, "1");
        }

        private void popDelete_Click(object sender, EventArgs e)
        {
            (this.Parent.Parent as BasePannel).deleteModel();
        }

        private void popBuildCode_Click(object sender, EventArgs e)
        {
            (Parent.Parent as BasePannel).TraceEntityCode(this);
        }
        #endregion

        private void ClassObject_DoubleClick(object sender, EventArgs e)
        {
            const int Count = ModelDataDictionary.EntityTable.Count;
            DataTable tableTemp1 = this.entity.Clone();
            DataTable tableTemp2 = this.entity.Clone();
            tableTemp1.Columns[ModelDataDictionary.EntityTable.Type].DefaultValue = ClassSon.Attribute.ToString();
            tableTemp2.Columns[ModelDataDictionary.EntityTable.Type].DefaultValue = ClassSon.Method.ToString() ;
            DataRow dr = null;
            ///初始化Grid控件数据源

            for (int icount = 0; icount < this.entity.Rows.Count; icount++)
            {
                if (this.entity.Rows[icount][ModelDataDictionary.EntityTable.Type].ToString() == ClassSon.Attribute.ToString())
                {
                    tableTemp1.Rows.Add(dr = tableTemp1.NewRow());
                }
                else
                {
                    tableTemp2.Rows.Add(dr = tableTemp2.NewRow());
                }
                for(int i=0;i<Count;i++)
                    dr[i] = entity.Rows[icount][i].ToString();
            }

            do
            {
                ClassDialog classdialog = new ClassDialog(tableTemp1, tableTemp2, eDataRow);
                if (classdialog.ShowDialog() == DialogResult.Cancel) return;

                if (CheckSameName())
                {
                    this.Name = eDataRow[ModelDataDictionary.EntityTable.Name].ToString();
                    this.entity.TableName = this.Name;
                    break;
                }

                eDataRow[ModelDataDictionary.EntityTable.Name] = entity.TableName;

                switch(MessageBox.Show("有同名","有同名", MessageBoxButtons.OKCancel, MessageBoxIcon.Error))
                {
                    case DialogResult.OK:
                        break;
                    case DialogResult.Cancel:
                        return;
                        break;
                }
            } while ( true);

            entity.Clear();
            for (int icount = 0; icount < tableTemp1.Rows.Count; icount++)
            {
                this.entity.Rows.Add(dr = this.entity.NewRow());
                for (int i = 0; i < Count; i++)
                    dr[i] = tableTemp1.Rows[icount][i].ToString();
            }
            for (int icount = 0; icount < tableTemp2.Rows.Count; icount++)
            {
                this.entity.Rows.Add(dr=this.entity.NewRow());
                for(int i=0;i<Count;i++)
                    dr[i] = tableTemp2.Rows[icount][i].ToString();

            }	

            init();
        }
        private bool CheckSameName()
        {
            foreach (DataRow dr in (this.Parent.Parent as BasePannel).dsModel.Tables[ModelDataDictionary.MainClass.TableName].Rows)
            {
                if (dr == eDataRow) continue;

                if (dr[ModelDataDictionary.MainClass.Name].Equals( eDataRow[ModelDataDictionary.MainClass.Name]))
                    return false;

            }
            return true;
        }



    }
}